package com.atguigu.linklist;

//单向环形列表解决约瑟夫问题，链表的核心就是建立一个辅助指针，进行遍历、增加、update等等
public class Josepfu {

    public static void main(String[] args) {
        SingleLinkCirle slc = new SingleLinkCirle();
        slc.add(10);
        slc.outCircle(2,3,10);

    }
}

class SingleLinkCirle{
    //指向第一个节点
    private Boy first = null;

    //创建一个num节点个数的单向环形链表
    public void add(int num){
        if (num<1){
            System.out.println("输入num不正确，请输入num>1");
            return;
        }

        //利用curBoy作为辅助指针，构建环形链表
        Boy curBoy = null;

        for (int i =0; i<num; i++){
            Boy boy = new Boy(i);
            if (i==0){
                first = boy;
                first.setNext(first);
                curBoy = first;
            }else {
                curBoy.setNext(boy);
                boy.setNext(first);
                curBoy = boy;
            }
        }
    }

    public void show(){
        Boy boy = first;
        if (first == null){
            System.out.println("链表为null");
        }
        while (true){
            System.out.printf("%d节点\n",boy.getNo());
            if (boy.getNext()==first){
                break;
            }
            boy = boy.getNext();
        }
    }

    //根据用户输入，计算小孩出圈顺序
    public void outCircle(int start,int baoshu,int num){
        //首先判断输入数字是否正确和是否可以正常执行方法
        if (first == null || start <1 || start > num || baoshu < 1){
            System.out.println("请确认输入内容是否正确或链表是否为空");
            return;
        }
        //定义一个辅助节点，在开始节点的后面一个节点
        Boy help = first;
        while (true){
            help = help.getNext();
            if (help.getNext() == first){
                break;
            }
        }

        //将first和help定位到起始位置
        for (int i=0;i<start;i++){
            first = first.getNext();
            help = help.getNext();
        }

        //出圈
        for (int i=0;i<num;i++){
            for (int j=0;j<baoshu-1;j++){
                first = first.getNext();
                help = help.getNext();
            }
            System.out.printf("出圈的数为%d\n",first.getNo());
            first = first.getNext();
            help.setNext(first);
            if (first == help){
                System.out.printf("最后一个出圈的%d\n",first.getNo());
                break;
            }
        }

    }
}

class Boy{
    private int no;
    private Boy next;

    public Boy(int no){
        this.no = no;
    }

    public int getNo() {
        return no;
    }

    public void setNo(int no) {
        this.no = no;
    }

    public Boy getNext() {
        return next;
    }

    public void setNext(Boy next) {
        this.next = next;
    }
}